昨天我們掌握了用 TextField
接收使用者輸入的技巧。但如果想讓使用者發布「多則」留言,並像聊天室一樣顯示出來,該怎麼辦?
這就是 iOS App 中王者級元件—— 列表(TableView) 登場的時刻了!從 Instagram 的動態牆到手機的「設定」選單,TableView 無所不在,是呈現大量、可滑動資料的唯一正解。
今天,我們將透過實作一個簡單的「留言板」,來學習 TableView
的運作核心,並親手打造出你的第一個動態滾動列表!
TableViewCell
:學習建立自己的 Cell
樣式,並了解其重要性TableView
的三大支柱:深入理解 register
(註冊樣板)、dataSource
(提供資料)與 delegate
(處理互動)的核心分工dataSource
:掌握 numberOfRowsInSection
和 cellForRowAt
這兩個必備方法,告訴 TableView
要顯示什麼reloadData()
,在資料變動時即時刷新 TableView
的畫面我們先建立自訂的 TableViewCell
,用來顯示每筆留言。
對專案資料夾按右鍵,選擇 New File from Template...
:
選擇 Cocoa Touch Class
:
Class
名稱填 MainTableViewCell
,Subclass of
選擇 UITableViewCell
,並勾選 Also create XIB file
,確認後按下 Next
:
確認檔案儲存位置後,按下 Create
:
完成後,會在左側檔案管理看到新增的 MainTableViewCell.swift
跟 MainTableViewCell.xib
。
在 TableView
裡,每一列(Row)都是由 Cell
負責呈現。
如果使用系統內建的 Cell
,只能顯示簡單的文字或圖片,外觀很死板。
自訂 Cell
可以讓我們:
TableView
會自動重複使用這個模板來產生每一列,節省記憶體。這樣我們就能讓留言板的每一筆留言看起來一致又美觀。
打開 MainTableViewCell.xib
,在畫面上放一個 Label
,並用 Auto Layout
設定約束(非常重要,避免跑版),建議寬度拉長一點,這樣待會留言的內容才會正確顯示:
並建立 IBOutlet
(從 xib
拉到 swift
檔案中,可參考前面的文章):
@IBOutlet weak var lbText: UILabel!
回到 MainViewController.xib
,放入:
TextField
,命名為 txfMessage
Button
,命名為 btnEnter
TableView
,命名為 tbvMessage
使用 Auto Layout
確保元件位置合適、大小固定。
接著在 MainViewController.swift
中宣告連結跟變數:
@IBOutlet weak var txfMessage: UITextField!
@IBOutlet weak var btnEnter: UIButton!
@IBOutlet weak var tbvMessage: UITableView!
var messages: [String] = [] //儲存留言內容
送出按鈕動作(從 xib
拉到 swift
檔案中,一樣可以參考前面的文章):
@IBAction func didTapButton(_ sender: UIButton) {
guard let text = txfMessage.text?.trimmingCharacters(in: .whitespacesAndNewlines), !text.isEmpty else {
return
}
messages.append(text)
tbvMessage.reloadData()
txfMessage.text = ""
// 新增:送出後收起鍵盤
txfMessage.resignFirstResponder()
// 或者用 view.endEditing(true) 也可以
}
在 viewDidLoad()
裡設定:
override func viewDidLoad() {
super.viewDidLoad()
// 讀取我們剛剛做的 MainTableViewCell.xib,讓 TableView 知道要用它來顯示每一列
let nib = UINib(nibName: "MainTableViewCell", bundle: nil)
tbvMessage.register(nib, forCellReuseIdentifier: "MainTableViewCell")
// 告訴 TableView,「資料從哪裡來」(DataSource)
tbvMessage.dataSource = self
// 告訴 TableView,「互動事件誰來處理」(Delegate)
tbvMessage.delegate = self
}
register()
MainTableViewCell
這個名字(reuseIdentifier
),指的就是這張 Xib 設計圖dataSource
(資料來源)TableView
:UITableViewDataSource
裡面回答這些問題。delegate
(代理人)TableView
:可以把 TableView
想成一個「清單展示舞台」:register()
→ 舞台的布景設計(決定每一列的長相)dataSource
→ 送資料的人(負責準備每一列的內容)delegate
→ 處理互動的人(負責回應使用者操作)
這段程式碼是告訴 TableView
:
extension MainViewController: UITableViewDataSource, UITableViewDelegate {
// 1️⃣ 告訴 TableView:一共有幾列資料要顯示
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
// 2️⃣ 告訴 TableView:每一列要用什麼 Cell,內容是什麼
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// 從「可重複利用的 Cell 倉庫」取出一個 MainTableViewCell
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MainTableViewCell", for: indexPath) as? MainTableViewCell else {
return UITableViewCell()
}
// 設定這一列要顯示的文字
cell.lbText.text = messages[indexPath.row]
return cell
}
// 3️⃣ 處理使用者點擊這一列的事件
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("你點了第 \(indexPath.row + 1) 筆留言:\(messages[indexPath.row])")
// 讓點擊效果消失(不會一直反白)
tableView.deselectRow(at: indexPath, animated: true)
}
}
numberOfRowsInSection
messages.count
直接回傳留言數量。cellForRowAt
dequeueReusableCell
withIdentifier
)去倉庫領取一個可用的 Cell
。如果倉庫裡有閒置的 Cell
,系統就直接拿來用;如果沒有,它會用你註冊的模板自動產生一個新的。這個機制大大提升了效能。didSelectRowAt
deselectRow
你可以把 TableView
想成餐廳點餐流程:numberOfRowsInSection
→ 有幾道菜(幾列資料)cellForRowAt
→ 每道菜要怎麼上桌(每列怎麼顯示)didSelectRowAt
→ 客人點了哪道菜後要做什麼(互動回應)
點擊執行按鈕,啟動模擬器,來看看我們的留言板實際效果。
我這裡已經輸入了 20 筆留言,透過上下滑動可以順暢瀏覽所有資料:
接著,點擊任一筆留言,Xcode 的 Console 會即時印出你點擊的是哪一筆:
這樣我們就成功完成了動態列表與點擊互動的功能!
太棒了!今天你親手打造了 iOS App 中最重要的元件之一:TableView
!
我們透過「留言板」的實作,完整走過了 TableView
的生命週期:從設計一個自訂的 Cell
,到在 viewDidLoad
中完成三大核心設定(register
, dataSource
, delegate
),最後透過實作 dataSource
的兩個關鍵方法,成功地將資料顯示在畫面上。
你現在不僅理解了 TableView
的運作原理,更學會了如何用 reloadData()
來動態更新列表。這是你從打造靜態畫面,邁向動態資料呈現的關鍵一步!
今天的留言板功能很棒,但還有優化的空間!如果想編輯已經發布的留言,而不是只能一直新增,該怎麼做?
明天,我們將為這個專案追加「編輯」功能。你將學會如何偵測使用者點擊了哪一筆留言、將該留言的內容傳回上方的 TextField
,並在使用者修改完畢後,更新 TableView
中對應的資料,而不是新增一筆。這將讓你的 App 互動邏輯更完整、更實用!
敬請期待 《Day 22|Xcode 互動進階:點擊編輯留言,動態更新列表》